#pragma once
#include <iostream>
#include <string>
#include <functional>
#include <cstdlib>
#include <cstring>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <unistd.h>
#include <pthread.h>
#include "InetAddr.hpp"
#include "socket.hpp"
using namespace socket_ns;
class TcpServer;

struct threaddata
{
    threaddata(socket_sptr fd, InetAddr &addr, TcpServer *tp) : _fd(fd), _addr(addr), _self(tp)
    {
    }
    socket_sptr _fd;
    InetAddr _addr;
    TcpServer *_self;
};
using http_t=std::function<std::string(std::string)>;

class TcpServer
{
public:
    TcpServer(uint16_t port,http_t service)
        : _localaddr("0", port)
        , _listensock(std::make_unique<TcpSocket>())
        ,_service(service)
        ,_isrunning(false)
    {
        _listensock->BuildListenSocket(_localaddr);
    }

    
    static void *newthreaddo(void *arg)
    {
        pthread_detach(pthread_self());
        threaddata *ptd = static_cast<threaddata *>(arg);
        std::string request,response;
        int n=ptd->_fd->Recv(&request);
        if(n>0)
        {
            response=ptd->_self->_service(request);
            ptd->_fd->Send(response);
        }
        ptd->_fd->Close();
        delete ptd;
        return nullptr;
    }
    void StartServer()
    {
        _isrunning=true;
        while (true)
        {
            InetAddr clientaddr;
            socket_sptr normalsock=_listensock->AcceptIt(&clientaddr);
            if(normalsock==nullptr)continue;

            pthread_t t; // 多线程
            threaddata *ptd = new threaddata(normalsock, clientaddr, this);
            pthread_create(&t, nullptr, newthreaddo, ptd);
        }
    }

    ~TcpServer()
    {
    }

private:
    std::unique_ptr<Socket> _listensock;
    InetAddr _localaddr;
    bool _isrunning;
    http_t _service;
};
